package top.byteio.common.core.crypto;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;

/**
 * <h3>对称加密算法</h3>
 * 对称加密算法加密和解密使用的是同一份秘钥，解密是加密的逆运算。
 * 对称加密算法加密速度快，密文可逆，一旦秘钥文件泄露，就会导致原始数据暴露。
 * 对称加密的结果一般使用Base64算法编码，便于阅读和传输。
 * JDK8支持的对称加密算法主要有DES、DESede、AES、Blowfish，以及RC2和RC4等。不同的算法秘钥长度不同，秘钥长度越长，加密安全性越高。
 * <p>
 * AES（AdvancedEncryption Standard，高级数据加密标准）算法支持128位、192位和256位的秘钥长度,
 * 加密速度比DES和DESede都快，至今还没有被破解的报道。经过验证，
 * 目前采用的AES算法能够有效抵御已知的针对DES算法的所有攻击方法，如部分差分攻击、相关秘钥攻击等。
 * AES算法因秘钥建立时间短、灵敏性好、内存需求低等优点，在各个领域得到广泛的研究与应用。</p>
 *
 * @author lerry
 * @since 2023/6/22 19:16
 */
public class AES implements ICrypt {

    private static final String ALGORITHM = "AES";

    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";

    /**
     * AES加密
     *
     * @param key  密钥
     * @param data 数据
     * @return byte[] 被加密数据
     * @throws Exception 异常
     * @author lerry
     * @since 2023/6/22 19:42
     */
    public static byte[] encrypt(byte[] key, byte[] data) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
        return cipher.doFinal(data);
    }

    /**
     * AES加密
     *
     * @param key  密钥
     * @param data 数据
     * @return String 被加密数据
     * @throws Exception 异常
     * @author lerry
     * @since 2023/6/22 19:42
     */
    public static String encrypt(String key, String data) throws Exception {
        byte[] keyBytes = key.getBytes();
        byte[] dataBytes = data.getBytes();
        byte[] encrypt = encrypt(keyBytes, dataBytes);
        return new String(encrypt);
    }

    /**
     * AES解密
     *
     * @param key           密钥
     * @param encryptedData 被加密数据
     * @return byte[]  数据
     * @throws Exception 异常
     * @author lerry
     * @since 2023/6/22 19:37
     */
    public static byte[] decrypt(byte[] key, byte[] encryptedData) throws Exception {
        SecretKeySpec secretKeySpec = new SecretKeySpec(key, ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);
        return cipher.doFinal(encryptedData);
    }

    /**
     * AES解密
     *
     * @param key           密钥
     * @param encryptedData 被加密数据
     * @return String  数据
     * @throws Exception 异常
     * @author lerry
     * @since 2023/6/22 19:37
     */
    public static String decrypt(String key, String encryptedData) throws Exception {
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        byte[] encryptedDataBytes = encryptedData.getBytes(StandardCharsets.UTF_8);
        byte[] decrypt = decrypt(keyBytes, encryptedDataBytes);
        return new String(decrypt);
    }
}
